#pragma once

#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"
#include "Log.hpp"
using namespace EpollMoudle;
using namespace LogMoudle;
class Reactor
{
    static const int revs_num = 128;

private:
    bool IsConnectionHelper(int sockfd)
    {
        auto e = _mmap.find(sockfd);
        if (e == _mmap.end())
        {
            return false;
        }
        return true;
    }
    bool IsConnectionEmpty()
    {
        return _mmap.empty();
    }
    int looponce(int timeout)
    {
        return _epoller_ptr->WaitEvents(_revs, revs_num, timeout);
    }
    bool IsConnectionExist(std::shared_ptr<Connection> &as)
    {
        return IsConnectionHelper(as->GetFd());
    }
    bool IsConnectionExist(int sockfd)
    {
        return IsConnectionHelper(sockfd);
    }
    void Dispatcher(int n)
    {
        for (int i = 0; i < n; i++)
        {
            uint32_t event = _revs[i].events;
            int sockfd = _revs[i].data.fd;
            // 1. 将所有的异常处理，统一转化成IO错误 2. 所有的IO异常，统一转换成为一个异常处理函数
            if (event & EPOLLERR) // 发生错误
            {
                event |= (EPOLLOUT | EPOLLIN);
            }
            if (event & EPOLLHUP) // 连接终止
            {
                event |= (EPOLLOUT | EPOLLIN);
            }
            if (event & EPOLLIN) // 读事件
            {
                if (IsConnectionExist(sockfd))
                {
                    _mmap[sockfd]->Recver();
                }
            }
            if (event & EPOLLOUT) // 写事件
            {
                if (IsConnectionExist(sockfd))
                {
                    _mmap[sockfd]->Sender();
                }
            }
        }
    }

public:
    Reactor()
        : _epoller_ptr(std::make_unique<Epoller>()), _isrunning(false)
    {
    }
    void loop() // 启动
    {
        if (IsConnectionEmpty())
        {
            return;
        }
        _isrunning = true;
        int timeout = -1;
        while (_isrunning)
        {
            PrintConnection();
            int n = looponce(timeout);
            Dispatcher(n); // 处理已就绪的事件
        }
        _isrunning=false;
    }
    void AddConnection(std::shared_ptr<Connection> &as)
    {
        // 0. 不要重复添加
        if (IsConnectionExist(as))
        {
            LOG(loglevel::WARNING) << "conn is exists: " << as->GetFd();
            return;
        }
        // 1. conn对应的fd和他要关心的事件，写透到内核中！
        uint32_t event = as->GetEvent();
        int fd = as->GetFd();
        _epoller_ptr->AddEvent(fd, event);
        // 2. 设置当前conn的拥有者回指指针
        as->SetOwner(this);
        // 3. 将具体的connection添加到_mmap
        _mmap[fd] = as;
    }
    void DelConnection(int sockfd)
    {
        _epoller_ptr->DelEvent(sockfd);
        _mmap.erase(sockfd);
        close(sockfd);
         LOG(loglevel::INFO) << "client quit: " << sockfd;
    }
    void Stop()
    {
        _isrunning = false;
    }
    void PrintConnection()
    {
        std::cout << "当前Reactor正在进行管理的fd List:";
        for (auto &conn : _mmap)
        {
            std::cout << conn.second->GetFd() << " ";
        }
        std::cout << "\r\n";
    }
    void EnableReadWrite(int sockfd, bool as, bool aq)
    {
        // 0. 不要重复添加
        if (!IsConnectionExist(sockfd))
        {
            LOG(loglevel::WARNING) << "EnableReadWrite, conn is exists: " << sockfd;
            return;
        }
        // 1. 修改当前sockfd对应的connection关心的事件
        uint32_t new_event=(EPOLLET|(as?EPOLLIN:0)|(aq?EPOLLOUT:0));
        _mmap[sockfd]->SetEvent(new_event);
        _epoller_ptr->ModEvent(sockfd,new_event);
    }
    ~Reactor()
    {
    }

private:
    // epoll模型
    std::unique_ptr<Epoller> _epoller_ptr;
    // 管理所有的connection
    std::unordered_map<int, std::shared_ptr<Connection>> _mmap;
    // 是否启动
    bool _isrunning;
    // 所有就绪事件
    struct epoll_event _revs[revs_num];
};